﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BS.Utilities;
using System.IO;
using System.Xml;

namespace WebMonitoring
{
    public partial class Website_Monitoring : Form
    {

        #region--- Variables---

        Ping netMon;
        string[] url;
        int[] interval;
        int[] count;
        bool[] flags;

        #endregion

        #region---Form's Events

        public Website_Monitoring()
        {
            InitializeComponent();

        }

        private void Website_Monitoring_Resize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized == WindowState)
            {
                this.Hide();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            netMon = new Ping();
            LoadSavedSites();
        }

        private void notifyIcon_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
            WindowState = FormWindowState.Normal;
        }

        private void miOpen_Click(object sender, EventArgs e)
        {
            this.Show();
            WindowState = FormWindowState.Normal;
        }

        private void btnCheckSite_Click(object sender, EventArgs e)
        {
            if (checkExistedAddress(txtSite.Text))
            {
                MessageBox.Show("This page has existed in the list.\n Please try another.",
                                "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtSite.Text = "http://";
                return;
            }
            try
            {
                int reply = WebStatus.GetGroupOfPageStatus(txtSite.Text.Trim());
                string status = "";
                switch (reply)
                {
                    case 1:
                        status = "OK";
                        break;
                    default:
                        status = "KO";
                        break;
                }
                AddNodeToXML(txtSite.Text.Trim(), txtInterval.Text.Trim(), status, DateTime.Now.ToString("MM-yy-yyyy: hh-mm-ss"), "logs/" + txtSite.Text.Substring(7));
                string[] val = { txtSite.Text.Trim(), txtInterval.Text.Trim(), status, DateTime.Now.ToString("MM-yy-yyyy: hh-mm-ss"), "logs/" + txtSite.Text.Substring(7) };
                dgvSiteList.Rows.Add(val);
                dgvSiteList[2, dgvSiteList.RowCount - 1].Value = "";
                dgvSiteList[2, dgvSiteList.RowCount - 1].Style.BackColor = Color.Yellow;
                string[] url2 = new string[url.Length + 1];
                for (int i = 0; i < url.Length; i++)
                {
                    url2[i] = url[i];
                }
                url2[url.Length] = txtSite.Text.Trim();
                int[] interval2 = new int[interval.Length + 1];
                for (int i = 0; i < url.Length; i++)
                {
                    interval2[i] = interval[i];
                }
                interval2[url.Length] = Convert.ToInt32(txtInterval.Text);
                int[] count2 = new int[count.Length + 1];
                for (int i = 0; i < count.Length; i++)
                {
                    count2[i] = count[i];
                }
                count2[count.Length] = 0;
                bool[] flags2 = new bool[flags.Length + 1];
                for (int i = 0; i < flags.Length; i++)
                {
                    flags2[i] = flags[i];
                }
                flags2[flags.Length] = true;

                url = url2;
                interval = interval2;
                count = count2;
                flags = flags2;

            }
            catch (Exception)
            {

            }


        }

        private void txtSite_Click(object sender, EventArgs e)
        {
            txtSite.Select(7, txtSite.Text.Length);
        }

        private void Timer_AutoCheck_Tick(object sender, EventArgs e)
        {
            try
            {
                for (int i = 0; i < count.Length; i++)
                {
                    ++(count[i]);
                    if (count[i] >= interval[i] && flags[i] == true)
                    {
                        int reply = WebStatus.GetGroupOfPageStatus(url[i]);
                        switch (reply)
                        {
                            case 1:
                                dgvSiteList[2, i].Style.BackColor = Color.GreenYellow;
                                break;
                            default:
                                dgvSiteList[2, i].Style.BackColor = Color.Red;
                                break;
                        }
                        count[i] = 0;

                        //
                        string date = DateTime.Now.ToString("MM-dd-yyyy hh:mms tt");
                        UpdateSiteList("logs/sites.xml", dgvSiteList.Rows[i].Cells["colSiteName"].Value.ToString(),
                                        reply.ToString(), date);
                    }
                }
            }
            catch (Exception)
            {

            }
        }

        private void miClose_Click(object sender, EventArgs e)
        {
            this.Close();
            this.Dispose();
        }

        private void dgvSiteList_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (dgvSiteList.SelectedRows.Count != 1)
            {
                btnCheckAll.Enabled = false;
            }
            else
            {
                btnCheckAll.Enabled = true;
                if (flags[dgvSiteList.CurrentRow.Index] == true)
                {
                    btnCheckAll.Text = "Stop Checking";
                }
                else
                    btnCheckAll.Text = "Check";
            }
        }

        private void btnCheckAll_Click(object sender, EventArgs e)
        {
            if (btnCheckAll.Text.Trim() == "Check") // execute start check site
            {
                flags[dgvSiteList.CurrentRow.Index] = true;
                btnCheckAll.Text = "Stop Checking";
            }
            else // execute stop checking this site
            {
                flags[dgvSiteList.CurrentRow.Index] = false;
                btnCheckAll.Text = "Check";
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Do you want to delete this website?", "Warning!",
                               MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
            {

                try
                {
                    string pageAddress = dgvSiteList.CurrentRow.Cells["colSiteName"].Value.ToString();
                    DeletePagesFromXML(pageAddress);

                    dgvSiteList.Rows.RemoveAt(dgvSiteList.CurrentRow.Index);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

        }

        private void btnPing_Click(object sender, EventArgs e)
        {
            try
            {
                string pageAddress = dgvSiteList.CurrentRow.Cells["colSiteName"].Value.ToString().Substring(7);

                PingExc(pageAddress);
            }
            catch (Exception)
            {
                MessageBox.Show("Please choose a webpage from the list.");
            }
        }

        #endregion

        #region---Supporting Methods---

        private void PingExc(string pageAddress)
        {

            if (lstCheckStatus.Items.Count > 0)
            {
                lstCheckStatus.Items.Add("-------------------------------------");
            }
          
            PingResponse pingresponese = netMon.PingHost(pageAddress, 4);
            if (pingresponese == null)
            {
                lstCheckStatus.Items.Add("Error");
            }
            else
            {
                ProcessResponse(pingresponese);
                Timer_AutoCheck.Enabled = true;
            }
        }

        private void ProcessResponse(PingResponse response)
        {

            switch (response.PingResult)
            {
                case PingResponseType.Ok:
                case PingResponseType.RequestTimedOut:
                    foreach (int pingTime in response.ResponseTimes)
                    {
                        if (pingTime == Constants.InvalidInt)
                        {
                            lstCheckStatus.Items.Add("Ping Timeout");
                        }
                        else
                        {
                            lstCheckStatus.Items.Add("Reply from " + response.ServerEndPoint.Address.ToString() + ": time=" + pingTime);
                        }
                    }

                    lstCheckStatus.Items.Add("Ping stats for " + response.ServerEndPoint.Address.ToString());
                    lstCheckStatus.Items.Add("Packets: Sent = " + response.PacketsSent.ToString() + ", Received = " + response.PacketsReceived + ", Lost = " + response.Lost.ToString());
                    if (response.PacketsReceived > 0)
                    {
                        lstCheckStatus.Items.Add("Approximate times:");
                        lstCheckStatus.Items.Add("Minimum = " + response.MinimumTime + "ms, Maximum = " + response.MaximumTime + "ms, Average = " + response.AverageTime + "ms");
                    }

                    break;
                case PingResponseType.InternalError:
                    lstCheckStatus.Items.Add("Internal Error occurred: " + response.ErrorMessage);
                    break;
                case PingResponseType.ConnectionError:
                    lstCheckStatus.Items.Add("Connection Error: " + response.ErrorMessage);
                    break;
                case PingResponseType.CouldNotResolveHost:
                    lstCheckStatus.Items.Add("Could not resolve host");
                    break;
            }
        }

        //add node to xml file
        private void AddNodeToXML(string name ,string interval, string status, string lastcheck, string logpath)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("logs/sites.xml");
            XmlElement NewSite =  xmlDoc.CreateElement ("SITE");
            
            //XmlAttribute SiteId = xmlDoc.CreateAttribute("ID");
            //SiteId.Value = "";
            
            NewSite.InnerXml = "<NAME>" + name + "</NAME>" +
                               "<INTERVAL>" + interval   + "</INTERVAL>"+
                               "<STATUS>" + status   + "</STATUS>"+
                               "<LASTCHECK>" + lastcheck  + "</LASTCHECK>"+
                               "<LOGFILE>" + logpath  + "</LOGFILE>"
                               ;
            xmlDoc.DocumentElement.AppendChild(NewSite);
            xmlDoc.Save("logs/sites.xml");
        }

        private void LoadSavedSites()
        {
            string filepath = "logs/sites.xml";

            if (!Directory.Exists("logs"))
                Directory.CreateDirectory("logs");

            if (!File.Exists(filepath))
            {
                // Create new file
                string xmlContent = "<?xml version='1.0' encoding='utf-8'?><SITES></SITES>";
                FileUtility.Write(filepath, xmlContent, false);
                MessageBox.Show("No site added!");
                return;
            }

            //DataSet sites = new DataSet();
            //sites.ReadXml(filepath);
            //dgvSiteList.DataSource = sites;
            AddDataToGridView(filepath);
            AddInterval(filepath);
        }

        private void AddDataToGridView(string sourceFile)
        {
            XmlDocument dataSource = new XmlDocument();
            dataSource.Load(sourceFile);
            XmlNodeList sites = dataSource.GetElementsByTagName("SITE");

            foreach (XmlNode site in sites)
            {
                XmlNodeList atts = site.ChildNodes;
                string[] values = new string[atts.Count];
                for (int i = 0; i < atts.Count; i++)
                    values[i] = atts[i].InnerText;
                dgvSiteList.Rows.Add(values);
                //if (dgvSiteList[2, dgvSiteList.Rows.Count - 1].Value.ToString() == "OK")
                {
                    dgvSiteList[2, dgvSiteList.Rows.Count - 1].Style.BackColor = Color.Yellow;
                    dgvSiteList[2, dgvSiteList.Rows.Count - 1].Value = "";
                }
            }
        }

        private void AddInterval(string sourceFile)
        {
            XmlDocument dataSource = new XmlDocument();
            dataSource.Load(sourceFile);

            XmlNodeList names = dataSource.GetElementsByTagName("NAME");
            url = new string[names.Count];
            for (int i = 0; i < names.Count; i++)
                url[i] = names[i].InnerText;

            XmlNodeList intervals = dataSource.GetElementsByTagName("INTERVAL");
            interval = new int[intervals.Count];
            count = new int[intervals.Count];
            flags = new bool[intervals.Count];
            for (int i = 0; i < intervals.Count; i++)
            {
                interval[i] = Int32.Parse(intervals[i].InnerText) * 60 * 1000 / Timer_AutoCheck.Interval;
                count[i] = 0;
                flags[i] = true;
            }

        }

        private bool checkExistedAddress(string newPageAddress)
        {
            for (int i = 0; i < dgvSiteList.Rows.Count; i++)
            {
                string oldPageAddress = dgvSiteList.Rows[i].Cells["colSiteName"].Value.ToString();

                if (oldPageAddress.Equals(newPageAddress))
                {
                    return true;
                }
            }
            return false;
        }

        private void DeletePagesFromXML(string pageAddress)
        {
            string filePath = "logs/sites.xml";

            XmlDocument xmlDocument = new XmlDocument();
            if (File.Exists(filePath))
            {
                xmlDocument.Load(filePath);

                //get a reference to the root node
                XmlElement root = xmlDocument.DocumentElement;

                //create a list of sites
                XmlNodeList lstSites = xmlDocument.GetElementsByTagName("SITE");

                try
                {
                    //visit each site
                    foreach (XmlNode node in lstSites)
                    {
                        //within a site, createa list of its children
                        XmlNodeList lstChildren = node.ChildNodes;
                        {
                            foreach (XmlNode dir in lstChildren)
                            {
                                //if the child node is match to pageAddress needs to delete
                                if (dir.InnerText == pageAddress)
                                {
                                    root.RemoveChild(node);

                                    //save the file
                                    xmlDocument.Save(filePath);

                                    //stop
                                    break;
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                }
            }
        }

        private void UpdateSiteList(string sourceFile, string url, string status, string date)
        {
            XmlDocument sites = new XmlDocument();
            sites.Load(sourceFile);

            XmlNodeList names = sites.GetElementsByTagName("NAME");
            XmlNodeList statuss = sites.GetElementsByTagName("STATUS");
            XmlNodeList dates = sites.GetElementsByTagName("LASTCHECK");
            for (int i = 0; i < names.Count; i++)
            {
                if (names[i].InnerText == url)
                {
                    statuss[i].InnerText = status;
                    dates[i].InnerText = date;
                }
            }

            sites.Save(sourceFile);
        }

        #endregion

    }
}
